/********************************************************************************
* @file    bsp_uart.c
* @author  jianqiang.xue
* @version V1.0.0
* @date    2021-10-08
* @brief   uart驱动
********************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "RTE_Components.h"
#include CMSIS_device_header

#include "bsp_gpio.h"
#include "bsp_exti.h"
#include "bsp_uart.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

/* Private Define ------------------------------------------------------------*/
#define AF_TXD                                   0
#define AF_RXD                                   1

/* Private Typedef -----------------------------------------------------------*/
typedef void(*bsp_uart_callback)(void);

/* Private Variables ---------------------------------------------------------*/
#if BS_UART0_EN
#define BSP_UART0                                USART1
#define BSP_UART0_APBX_CLOCK()                   RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); \
                                                 RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_USART1, ENABLE)
#define BSP_UART0_IRQN                           USART1_IRQn
#define BSP_UART0_IRQ_HANDLER                    USART1_IRQHandler

// 定义串口信息初始化结构体
USART_InitType huart0 =
{
    .USART_BaudRate            = BS_UART0_BAUD_RATE,
    .USART_StopBits            = USART_StopBits_1,
    .USART_WordLength          = USART_WordLength_8b,
    .USART_Parity              = USART_Parity_No,
    .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
    .USART_Mode                = USART_Mode_Rx | USART_Mode_Tx
};

// 定义串口缓存区
uint8_t bsp_uart0_tx_buff[BS_UART0_CACHE_SIZE] = {0};
uint8_t bsp_uart0_rx_buff[BS_UART0_CACHE_SIZE] = {0};

// 定义串口初始化标记位 0--未初始化 1--初始化完成
bool g_uart0_init                              = false;
// 定义串口发送标记位 0--free闲  1--bus忙
bool g_uart0_send_lock                         = false;
// 记录当前接收长度
uint8_t g_uart0_rx_len                         = 0;
// 定义串口接收回调函数
static bsp_uart_callback uart0_irq_rx_callback;
#endif

#if BS_UART1_EN
#define BSP_UART1                                USART2
#define BSP_UART1_APBX_CLOCK()                   RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); \
                                                 RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_USART2, ENABLE)
#define BSP_UART1_IRQN                           USART2_IRQn
#define BSP_UART1_IRQ_HANDLER                    USART2_IRQHandler

// 定义串口信息初始化结构体
USART_InitType huart1 =
{
    .USART_BaudRate            = BS_UART1_BAUD_RATE,
    .USART_StopBits            = USART_StopBits_1,
    .USART_WordLength          = USART_WordLength_8b,
    .USART_Parity              = USART_Parity_No,
    .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
    .USART_Mode                = USART_Mode_Rx | USART_Mode_Tx
};

// 定义串口缓存区
uint8_t bsp_uart1_tx_buff[BS_UART1_CACHE_SIZE] = {0};
uint8_t bsp_uart1_rx_buff[BS_UART1_CACHE_SIZE] = {0};

// 定义串口初始化标记位 0--未初始化 1--初始化完成
bool g_uart1_init                              = false;
// 定义串口发送标记位 0--free闲  1--bus忙
bool g_uart1_send_lock                         = false;
// 记录当前接收长度
uint8_t g_uart1_rx_len                         = 0;
// 定义串口接收回调函数
static bsp_uart_callback uart1_irq_rx_callback;
#endif

#if BS_UART2_EN
#define BSP_UART2                                USART3
#define BSP_UART2_APBX_CLOCK()                   RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE); \
                                                 RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_USART3, ENABLE)
#define BSP_UART2_IRQN                           USART3_IRQn
#define BSP_UART2_IRQ_HANDLER                    USART3_IRQHandler

// 定义串口信息初始化结构体
USART_InitType huart2 =
{
    .USART_BaudRate            = BS_UART2_BAUD_RATE,
    .USART_StopBits            = USART_StopBits_1,
    .USART_WordLength          = USART_WordLength_8b,
    .USART_Parity              = USART_Parity_No,
    .USART_HardwareFlowControl = USART_HardwareFlowControl_None,
    .USART_Mode                = USART_Mode_Rx | USART_Mode_Tx
};

// 定义串口缓存区
uint8_t bsp_uart2_tx_buff[BS_UART2_CACHE_SIZE] = {0};
uint8_t bsp_uart2_rx_buff[BS_UART2_CACHE_SIZE] = {0};

// 定义串口初始化标记位 0--未初始化 1--初始化完成
bool g_uart2_init                              = false;
// 定义串口发送标记位 0--free闲  1--bus忙
bool g_uart2_send_lock                         = false;
// 记录当前接收长度
uint8_t g_uart2_rx_len                         = 0;
// 定义串口接收回调函数
static bsp_uart_callback uart2_irq_rx_callback;
#endif

/* Public Function Prototypes ------------------------------------------------*/
/**
 * @brief  设置串口波特率
 * @param  uart: 串口组号
 * @param  baud: 波特率
 */
void biz_uart_set_baud_rate(bsp_uart_t uart, uint32_t baud)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        huart0.USART_BaudRate = baud;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        huart1.USART_BaudRate = baud;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        huart2.USART_BaudRate = baud;
#endif
    }
    return;
}

/**
 * @brief  串口初始化
 * @param  uart: 串口组号
 */
void bsp_uart_init(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (g_uart0_init)
        {
            return;
        }
        bsp_exit_set(BSP_UART0_IRQN, 0);

        BS_UART0_RX_GPIO_CLK_ENABLE();
        BS_UART0_TX_GPIO_CLK_ENABLE();

        bsp_gpio_init_uart(BS_UART0_TX_GPIO_PORT, BS_UART0_TX_PIN, AF_TXD);
        bsp_gpio_init_uart(BS_UART0_RX_GPIO_PORT, BS_UART0_RX_PIN, AF_RXD);

        BSP_UART0_APBX_CLOCK();

        /* Configure USART0 */
        USART_Init(BSP_UART0, &huart0);
        g_uart0_rx_len = 0;
        USART_INTConfig(BSP_UART0, USART_INT_RDNE, ENABLE);
        /* Enable the USART0 */
        USART_Cmd(BSP_UART0, ENABLE);
        g_uart0_init = true;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (g_uart1_init)
        {
            return;
        }
        bsp_exit_set(BSP_UART1_IRQN, 5);
        bsp_gpio_set_clk(GPIO_APBx, BS_UART1_RX_GPIO_CLK, true);
        bsp_gpio_set_clk(GPIO_APBx, BS_UART1_TX_GPIO_CLK, true);

        bsp_gpio_init_uart(BS_UART1_TX_GPIO_PORT, BS_UART1_TX_PIN, AF_TXD);
        bsp_gpio_init_uart(BS_UART1_RX_GPIO_PORT, BS_UART1_RX_PIN, AF_RXD);

        BSP_UART1_APBX_CLOCK();

        /* Configure USART1 */
        USART_Init(BSP_UART1, &huart1);
        g_uart1_rx_len = 0;
        USART_INTConfig(BSP_UART1, USART_INT_RDNE, ENABLE);
        /* Enable the USART1 */
        USART_Cmd(BSP_UART1, ENABLE);
        g_uart1_init = true;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (g_uart2_init)
        {
            return;
        }
        bsp_exit_set(BSP_UART2_IRQN, 5);
        bsp_gpio_set_clk(GPIO_APBx, BS_UART2_RX_GPIO_CLK, true);
        bsp_gpio_set_clk(GPIO_APBx, BS_UART2_TX_GPIO_CLK, true);

        bsp_gpio_init_uart(BS_UART2_TX_GPIO_PORT, BS_UART2_TX_PIN, AF_TXD);
        bsp_gpio_init_uart(BS_UART2_RX_GPIO_PORT, BS_UART2_RX_PIN, AF_RXD);

        BSP_UART2_APBX_CLOCK();

        /* Configure USART2 */
        USART_Init(BSP_UART2, &huart2);
        g_uart2_rx_len = 0;
        USART_INTConfig(BSP_UART2, USART_INT_RDNE, ENABLE);
        /* Enable the USART2 */
        USART_Cmd(BSP_UART2, ENABLE);
        g_uart2_init = true;
#endif
    }
}

/**
 * @brief  串口反注册 关闭串口时钟并复位引脚
 * @param  uart: 串口组号
 */
void bsp_uart_deinit(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (!g_uart0_init)
        {
            return;
        }
        USART_Reset(BSP_UART0);
        bsp_gpio_deinit(BS_UART0_TX_GPIO_PORT, BS_UART0_TX_PIN);
        bsp_gpio_deinit(BS_UART0_RX_GPIO_PORT, BS_UART0_RX_PIN);
        g_uart0_init = false;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (!g_uart1_init)
        {
            return;
        }
        USART_Reset(BSP_UART1);
        bsp_gpio_deinit(BS_UART1_TX_GPIO_PORT, BS_UART1_TX_PIN);
        bsp_gpio_deinit(BS_UART1_RX_GPIO_PORT, BS_UART1_RX_PIN);
        g_uart1_init = false;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (!g_uart2_init)
        {
            return;
        }
        USART_Reset(BSP_UART2);
        bsp_gpio_deinit(BS_UART2_TX_GPIO_PORT, BS_UART2_TX_PIN);
        bsp_gpio_deinit(BS_UART2_RX_GPIO_PORT, BS_UART2_RX_PIN);
        g_uart2_init = false;
#endif
    }
}

/**
 * @brief  注册串口接收回调函数
 * @param  uart: 串口组号
 * @param  event: 事件回调函数
 * @retval 0--失败 1--成功
 */
bool bsp_uart_rx_irq_callback(bsp_uart_t uart, void *event)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (uart0_irq_rx_callback != NULL)
        {
            return true;
        }
        else
        {
            uart0_irq_rx_callback = (bsp_uart_callback)event;
        }
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (uart1_irq_rx_callback != NULL)
        {
            return true;
        }
        else
        {
            uart1_irq_rx_callback = (bsp_uart_callback)event;
        }
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (uart2_irq_rx_callback != NULL)
        {
            return true;
        }
        else
        {
            uart2_irq_rx_callback = (bsp_uart_callback)event;
        }
#endif
    }
    return false;
}

#if BS_UART0_EN
/**
  * @brief  This function handles USART global interrupt request.
  */
void BSP_UART0_IRQ_HANDLER(void)
{
    if (USART_GetITStatus(BSP_UART0, USART_INT_RDNE) != RESET)
    {
        /* Read one byte from the receive data register */
        bsp_uart0_rx_buff[g_uart0_rx_len++] = USART_ReceiveData(BSP_UART0);
        if (uart0_irq_rx_callback)
        {
            uart0_irq_rx_callback();
        }
        if (g_uart0_rx_len >= (BS_UART0_CACHE_SIZE - 1))
        {
            g_uart0_rx_len = 0;
        }
    }
}
#endif

#if BS_UART1_EN
/**
  * @brief  This function handles USART global interrupt request.
  */
void BSP_UART1_IRQ_HANDLER(void)
{
    if (USART_GetITStatus(BSP_UART1, USART_INT_RDNE) != RESET)
    {
        /* Read one byte from the receive data register */
        bsp_uart1_rx_buff[g_uart1_rx_len++] = USART_ReceiveData(BSP_UART1);
        if (uart1_irq_rx_callback)
        {
            uart1_irq_rx_callback();
        }
        if (g_uart1_rx_len >= (BS_UART1_CACHE_SIZE - 1))
        {
            g_uart1_rx_len = 0;
        }
    }
}
#endif

#if BS_UART2_EN
/**
  * @brief  This function handles USART global interrupt request.
  */
void BSP_UART2_IRQ_HANDLER(void)
{
    if (USART_GetITStatus(BSP_UART2, USART_INT_RDNE) != RESET)
    {
        /* Read one byte from the receive data register */
        bsp_uart2_rx_buff[g_uart2_rx_len++] = USART_ReceiveData(BSP_UART2);
        if (uart2_irq_rx_callback)
        {
            uart2_irq_rx_callback();
        }
        if (g_uart2_rx_len >= (BS_UART2_CACHE_SIZE - 1))
        {
            g_uart2_rx_len = 0;
        }
    }
}
#endif

/************************************[uart] 使用函数************************************/
/**
 * @brief  发送一个字节
 * @param  uart: 串口组号
 * @param  data: 字节值
 */
void bsp_uart_send_byte(bsp_uart_t uart, uint8_t data)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (!g_uart0_init)
        {
            return;
        }
        USART_SendData(BSP_UART0, data);
        //send data empty flag
        while(RESET == USART_GetFlagStatus(BSP_UART0,  USART_FLAG_TDE));
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (!g_uart1_init)
        {
            return;
        }
        USART_SendData(BSP_UART1, data);
        //send data empty flag
        while(RESET == USART_GetFlagStatus(BSP_UART1,  USART_FLAG_TDE));
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (!g_uart2_init)
        {
            return;
        }
        USART_SendData(BSP_UART2, data);
        //send data empty flag
        while(RESET == USART_GetFlagStatus(BSP_UART2,  USART_FLAG_TDE));
#endif
    }
    return;
}

/**
 * @brief  发送多个字节(堵塞)
 * @param  uart: 串口组号
 * @param  *data: 数据头指针
 * @param  len: 数据长度
 */
bool bsp_uart_send_nbyte(bsp_uart_t uart, uint8_t *data, uint16_t len)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (!g_uart0_init)
        {
            return false;
        }
        if (g_uart0_send_lock)
        {
            return false;
        }
        g_uart0_send_lock = true;
        if (data != NULL)
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_0, data[i]);
            }
        }
        else
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_0, bsp_uart0_tx_buff[i]);
            }
        }
        g_uart0_send_lock = false;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (!g_uart1_init)
        {
            return false;
        }
        if (g_uart1_send_lock)
        {
            return false;
        }
        g_uart1_send_lock = true;
        if (data != NULL)
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_1, data[i]);
            }
        }
        else
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_1, bsp_uart1_tx_buff[i]);
            }
        }
        g_uart1_send_lock = false;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (!g_uart2_init)
        {
            return false;
        }
        if (g_uart2_send_lock)
        {
            return false;
        }
        g_uart2_send_lock = true;
        if (data != NULL)
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_2, data[i]);
            }
        }
        else
        {
            for (uint16_t i = 0; i < len; i++)
            {
                bsp_uart_send_byte(BSP_UART_2, bsp_uart2_tx_buff[i]);
            }
        }
        g_uart2_send_lock = false;
#endif
    }
    return true;
}

/**
 * @brief  发送多个字节(非堵塞) 一般DMA方式
 * @param  uart: 串口组号
 * @param  *data: 数据头指针
 * @param  len: 数据长度
 */
void bsp_uart_send_nbyte_nowait(bsp_uart_t uart, uint8_t *data, uint16_t len)
{
    return;
}

/**
 * @brief  得到txbuff头指针
 * @param  uart: 串口组号
 */
uint8_t *bsp_uart_get_txbuff(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (g_uart0_send_lock == false)
        {
            return bsp_uart0_tx_buff;
        }
        return NULL;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (g_uart1_send_lock == false)
        {
            return bsp_uart1_tx_buff;
        }
        return NULL;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (g_uart2_send_lock == false)
        {
            return bsp_uart2_tx_buff;
        }
        return NULL;
#endif
    }
    return NULL;
}

/**
 * @brief  得到rxbuff头指针
 * @param  uart: 串口组号
 */
uint8_t *bsp_uart_get_rxbuff(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        return bsp_uart0_rx_buff;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        return bsp_uart1_rx_buff;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        return bsp_uart2_rx_buff;
#endif
    }
    return NULL;
}

/**
 * @brief  [串口信息] 返回串口缓存指针位置，即当前缓存数量（byte）
 * @param  uart: 串口号
 * @retval 串口缓存指针位置
 */
uint16_t bsp_uart_get_rxbuff_position(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        return g_uart0_rx_len;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        return g_uart1_rx_len;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        return g_uart2_rx_len;
#endif
    }
    return NULL;
}

/**
 * @brief  得到rxbuff大小
 * @param  uart: 串口组号
 * @retval 字节大小
 */
uint16_t bsp_uart_get_rxbuff_size(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        return BS_UART0_CACHE_SIZE;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        return BS_UART1_CACHE_SIZE;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        return BS_UART2_CACHE_SIZE;
#endif
    }
    return 0;
}

/**
 * @brief  [串口操作] 关闭串口接收：关闭串口中断，终止接收中断回调
 * @note   由于无DMA，只能先关闭，再处理数据，防止数据错乱。然后重新读取。
 * @param  uart: 串口号
 */
void bsp_uart_rx_close(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        if (!g_uart0_init)
        {
            return;
        }
        USART_Reset(BSP_UART0);
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        if (!g_uart1_init)
        {
            return;
        }
        USART_Reset(BSP_UART1);
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        if (!g_uart2_init)
        {
            return;
        }
        USART_Reset(BSP_UART2);
#endif
    }
    return;
}

/**
 * @brief  [串口操作] 打开串口接收：打开串口中断，设置接收中断回调
 * @note   由于无DMA，只能先关闭，再处理数据，防止数据错乱。然后重新读取。
 * @param  uart: 串口号
 */
void bsp_uart_rx_open(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        bsp_uart_init(BSP_UART_0);
        g_uart0_rx_len = 0;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        bsp_uart_init(BSP_UART_1);
        g_uart1_rx_len = 0;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        bsp_uart_init(BSP_UART_2);
        g_uart2_rx_len = 0;
#endif
    }
    return;
}

/**
 * @brief  [串口操作] 复位接收缓存指针
 * @param  uart: 串口号
 */
void bsp_uart_reset_rxbuff(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        g_uart0_rx_len = 0;
        memset(bsp_uart0_rx_buff, 0, BS_UART0_CACHE_SIZE);
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        g_uart1_rx_len = 0;
        memset(bsp_uart1_rx_buff, 0, BS_UART1_CACHE_SIZE);
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        g_uart2_rx_len = 0;
        memset(bsp_uart2_rx_buff, 0, BS_UART2_CACHE_SIZE);
#endif
    }
    return;
}

bool bsp_uart_get_bus(bsp_uart_t uart)
{
    if (uart == BSP_UART_0)
    {
#if BS_UART0_EN
        return g_uart0_send_lock;
#endif
    }
    else if (uart == BSP_UART_1)
    {
#if BS_UART1_EN
        return g_uart1_send_lock;
#endif
    }
    else if (uart == BSP_UART_2)
    {
#if BS_UART2_EN
        return g_uart2_send_lock;
#endif
    }
    return false;
}
